package client;import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.StringTokenizer;

import client.io.ConsoleInputManager;
import client.io.ConsoleOutputManager;
import client.network.SocketListener;

public class AuctionClient {

	private Socket serverConnection;
	private SocketListener listener;
	private int udpPortNumber;
	private int port;
	private String ip;

	public AuctionClient(String ip,int port,int udpPortNumber) {
		this.udpPortNumber = udpPortNumber;
		this.ip = ip;
		this.port = port;
		
	}

	public void startOperating() {
		
		while(true){
			try{
				String line = ConsoleInputManager.getNextCommand();
				StringTokenizer tokens = new StringTokenizer(line," ");
				
				String command = tokens.nextToken();
				/* parsing messages and adding them again to 
				 * socket message string is a provided 
				 * possibility back door (maybe seems unneeded 
				 * but pre-error checking mechanism)  */
				
				if(command.equals("!end")){
					logout();
					break;
				}
				else if(command.equals("!login")){
					String username = tokens.nextToken(); 
					login(username);
				}
				else if(command.equals("!logout")){
					logout();
				}
				else if(command.equals("!list")){
					list();
				}
				else if(command.equals("!create")){
					String duration = tokens.nextToken();
					String description = "";
					while(tokens.hasMoreTokens())
						description += " " +tokens.nextToken();
					description = description.substring(1);
					create(Integer.parseInt(duration), description);
				}
				else if(command.equals("!bid")){
					String id = tokens.nextToken();
					String amount = tokens.nextToken();
					bid(Integer.parseInt(id), Integer.parseInt(amount));
				}
				else
					ConsoleOutputManager.addNotify("Given command is unknown!");
			}catch(Exception e){
				ConsoleOutputManager.addNotify("Given command has errors.");
			}
		}
		destroyConnection();
	}

    private boolean createServer() {
        try {//connect to server
            serverConnection = new Socket( InetAddress.getByName(ip) , port);
        } catch (UnknownHostException e) {
            ConsoleOutputManager.throwWarning("Unknown exception has been thrown! This Peer will be closed!");
            return true;
        } catch (IOException e) {//server is off line
            ConsoleOutputManager.throwWarning("Given Server Adress is not correct!");
            ConsoleOutputManager.throwWarning("Server IP: "+ip+" Server Port: "+port);
            ConsoleOutputManager.throwWarning("This Peer will be closed!");
            return true;
        }

        DatagramSocket listeningSocket = null;
        try {
            listeningSocket = new DatagramSocket(udpPortNumber);
        } catch (IOException e) {
            ConsoleOutputManager.throwWarning("Given Listening socket is in use!");
            ConsoleOutputManager.throwWarning("This Peer will be closed!");
            return true;
        }
        listener = new SocketListener(this,listeningSocket);
        Thread t = new Thread(listener);
        t.start();//create thread for each peer connection


        sendMessage("!createConnection "+udpPortNumber);

        return false;
    }

    public void destroyConnection() {
		if(serverConnection != null){
			
			try {
				serverConnection.close();
				
			} catch (IOException e) {
			}
			serverConnection = null;
		}		
		if(listener != null){
			listener.stopListening();
			listener = null;
		}
	}
	
	

	private void bid(int id, int amount) {
		sendMessage("!bid "+id+" "+amount);
	}

	private void create(int duration, String description) {
		sendMessage("!create "+duration+" "+description);
	}

	private void list() {
		sendMessage("!list");
	}

	private void logout() {
		sendMessage("!logout");
	}

	private void login(String username) {
		sendMessage("!login "+username+" "+udpPortNumber);
	}

	private void sendMessage(String string) {
		if(serverConnection == null || serverConnection.isClosed() ){
            if (createServer())
                return;
		}

		BufferedWriter output;
		try {
			output = new BufferedWriter(new OutputStreamWriter(serverConnection.getOutputStream() ));
			output.write(string);//warn server about your being
			output.newLine();
			output.flush();
		} catch (IOException e) {
		}
	}

	
}
